/* -----------------------------------------------------------------------
 *   Copyright (C) 2008 by Denjs
 *   dplsoft@pisem.net
 *   http://qdroid.berlios.de
 * -----------------------------------------------------------------------
 *   This program is free software licensed under GNU GPL License v.2 ; see main.cpp fo details
 *   Эта программа является свободным программным обеспечением; распространяемым под
 *   лицензией GNU General Public License v.2 (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU версия 2.0) 
 * ----------------------------------------------------------------------- */
/*
 * t_FileList.cpp
 *
 * ver 2009.09.01
	- начаты работы над масками фильтрации при загрузке файла
	- надо бы добавить работу с фильрацией элементов по заданому условию...
 *   ver 2008.12.04
 *  Created on: 18.11.2008
 *      Author: Denjs
 */

#include "t_FileList.h"
//============================================================

t_FileList::t_FileList(QObject *parent)
		: t_AbstractQDroidBot(parent)
{
	if (DebugLevel>=3) qDebug()<<"t_FileList["<< get_id() <<"]::t_FileList (0027)[checkpoint]";
}
//============================================================
// needs to have ability to be included to QList
t_FileList::t_FileList(const t_FileList &other)// needs to be included to QList
{
	//qDebug()<<"t_FileListElement::t_FileListElement(t_FileListElement&):[0020]: other.Note1_inc =" << other.Note1_inc;
	////this->FileList=other.FileList;
	this->FileList.clear(); this->FileList+=(other.FileList);
	this->CurrentElementCopy=other.CurrentElementCopy;

	//return *this;
}
/**/

//============================================================
// needs to be included to QList
t_FileList& t_FileList::operator=(const t_FileList &other)
{
	//qDebug()<<"t_FileListElement::operator=:[0033]: other.Note1_inc =" << other.Note1_inc;
	this->FileList.clear();
	this->FileList+=(other.FileList);
	this->CurrentElementCopy=other.CurrentElementCopy;

	return *this;
}

//============================================================
/* virtual function to be redefined to make real class */
QString t_FileList::std_in(QString Message)
{
	return "ok";
}




//============================================================
/*добавить элемент*/
//добавить в заданную позицию
// => размер списка
int t_FileList::add(t_FileListElement *FileListElement,int position ) // =-1
{
	//TODO ввести проверку на выход позиции за границу списка!
	int Pos;
	if (position<0) Pos=FileList.size(); else Pos=position;
	CurrentElementCopy=*FileListElement;
	//qDebug()<<"t_FileList::add:[0041]: CurrentElementCopy.get_note1() =" << CurrentElementCopy.get_note1();

	FileList.insert(Pos, CurrentElementCopy);

	//t_FileListElement cp;
	//cp = FileListElement;
	// qDebug()<<"t_FileList::add:[0041]: CurrentElementCopy.get_note1() =" << CurrentElementCopy.get_note1();
	// qDebug()<<"t_FileList::add:[0042]: FileListElement->get_note1() =" << FileListElement->get_note1();

	/*/
	if (position<0)
		{  FileList.append(CurrentElementCopy);
		}
		else
		{  FileList.insert(position, CurrentElementCopy);
		  // FileList << FileListElement;
		};
	/**/
	this->CurrentElementCopy=FileList.value(Pos);
	//qDebug()<<"t_FileList::add:[0060]: Pos=["<<Pos<<"]. CurrentElementCopy.get_note1() =" << CurrentElementCopy.get_note1();

	return Pos;
}

//============================================================
// заменить элмент списка на хаданный
int t_FileList::replace(t_FileListElement *FileListElement,int position )
{
	//TODO ввести проверку на выход позиции за границу списка!
	CurrentElementCopy=*FileListElement;
	if ( (position<FileList.size()) & (position>=0) )
		{
			FileList.replace(position, CurrentElementCopy);
			return position;
		}
	else
		return -1;//некорректная позиция

}
//============================================================
//удалить элемент в позиции
int t_FileList::remove(int position)
{
	//TODO ввести проверку на выход позиции за границу списка!
	FileList.removeAt(position);
	return FileList.size();
}

//============================================================
//удалить элемент в позиции
int t_FileList::clear()
{
	FileList.clear();
	return FileList.size();
}

/**/
//============================================================
//
//вернуть ссылку на копию элемента из заданной позиции.
//
t_FileListElement *t_FileList::get(int position)
//t_FileListElement t_FileList::get(int position)
{
	//2008.11.25 при вызове get() из скрипта, переменная в скрипте получит ссылку на элемент...
	// и этот элемент должен быть новым что бы при следующем get()
	// старые значения не менялись...

	t_FileListElement *El;
	El=new (t_FileListElement); //TODO: потенциальный баг: нехорошо так.. кто будет следть что бы память очистили?
	if ( (position<FileList.size()) & (position>=0) )
		*El=FileList.value(position);
	return El; //n/t/

//	//qDebug()<<"t_FileList::get_element:[0073]: position=["<<position<<"]. CurrentElementCopy.get_note1() =" << CurrentElementCopy.get_note1();
//	this->CurrentElementCopy=FileList.value(position);
//	//qDebug()<<"t_FileList::get_element:[0075]: position=["<<position<<"]. CurrentElementCopy.get_note1() =" << CurrentElementCopy.get_note1();
//	return &(this->CurrentElementCopy);

}

//===========================================================================
//2008.12.02_1530
int t_FileList::get_pos_by_id(QString _id_value)
{
	int i;
	for (i = 0; i != FileList.size(); i++)
	  {
		if (FileList[i].get_id()== _id_value) return i;
	  };
	return -1;
};
/**/

/**/
//============================================================
//вернуть количество элементво в списке
int t_FileList::size()
{
	return FileList.size();
}
//============================================================
//обновить список файлов из каталога
/*
	DirDeep - глубина просомтра подкаталогов. 0 - просмотреть только текущий каталог.
*/
QString t_FileList::update_from_dir(QString _DirectoryPath,int DirDeep,QString _MissFileMask)
{
	//ВНИМАНИЕ! это рекурсивная функция! очищать тут список файлов нельзя!
	QDir Dir=QDir(_DirectoryPath);
	if (!Dir.exists()) return "t_FileList["+get_id()+"]::update_from_dir:[00103]:ERROR: directory not found ["+_DirectoryPath+"]";
    Dir.setFilter(QDir::Files |QDir::AllDirs |QDir::NoDotAndDotDot |QDir::Hidden |QDir::System |QDir::NoSymLinks );
    Dir.setSorting(QDir::Size | QDir::Reversed);
	if (DebugLevel>=3) qDebug()<<"t_FileList["<< get_id() <<"]::update_from_dir (00188)[checkpoint] ";
	//qDebug()<<"DebugLevel["<< DebugLevel <<"]::update_from_dir (00189)[checkpoint]";


    QFileInfoList FList = Dir.entryInfoList();
    for (int i = 0; i < FList.size(); ++i)
		{
			QFileInfo fileInfo = FList.at(i);
			//2009.09.01.здесь надо пропускать файлы если их имя 
			// соответвует списку масок из заблокированных
			// fileInfo.baseName()
			// TODO список масок задается через разделитель "вертикальная черта" | 
			// добавить позже 
			if (_MissFileMask.isEmpty()==false) //если маска пропуска задана - 
			  { 
				if (DebugLevel>=3) qDebug()<<"t_FileList["<< get_id() <<"]::update_from_dir (00202)[checkpoint] verifing file" << fileInfo.fileName() << " ?= " << _MissFileMask ;
				QStringList FileMaskList = _MissFileMask.split("|", QString::SkipEmptyParts);
			 	QRegExp rx;
				QString tmps;
				for (;FileMaskList.isEmpty()==false;)
				  {
					tmps=FileMaskList.takeFirst();
					if (DebugLevel>=3) qDebug()<<"t_FileList["<< get_id() <<"]::update_from_dir (00209)[checkpoint] verifing mask ?= " << tmps ;
					rx.setPattern(tmps);
			 		rx.setPatternSyntax(QRegExp::Wildcard);
 			 		if (rx.exactMatch(fileInfo.fileName())) break;//тут надо прервать нутренний цикл ;
				  };
				if (rx.exactMatch(fileInfo.fileName())) continue;// а тут пропустить текущий элемент
			  }
			else
				if (DebugLevel>=3) qDebug()<<"t_FileList["<< get_id() <<"]::update_from_dir (00207)[checkpoint]";
;
			//qPrintable(QString("%1 %2").arg(fileInfo.size(), 10).arg(fileInfo.fileName())
			if (fileInfo.isDir())
				{
					//qDebug()<< "[+]" << fileInfo.fileName();
					//qDebug()<< "   " << fileInfo.fileName();
					CurrentElementCopy=t_FileListElement();
					CurrentElementCopy.FileFullName_inc=fileInfo.fileName();
					CurrentElementCopy.Note1_inc="";
					CurrentElementCopy.Note2_inc="[directory]";
					CurrentElementCopy.Path_inc=fileInfo.path();
					CurrentElementCopy.ID_inc=fileInfo.path()+"/"+fileInfo.fileName()+"";//слеш в конце?
					CurrentElementCopy.set_relpath(CurrentElementCopy.Path_inc);
					FileList.insert(FileList.size(), CurrentElementCopy);

					if (DirDeep>0) this->update_from_dir(fileInfo.path()+"/"+fileInfo.fileName(),DirDeep-1, _MissFileMask);
					//ВНИМАНИЕ! надо-бы ограничить глубину просмотра - на случай циклических ссылок
				}
			   else
				{
					//qDebug()<< "   " << fileInfo.fileName();
					CurrentElementCopy=t_FileListElement();
					CurrentElementCopy.FileFullName_inc=fileInfo.fileName();
					CurrentElementCopy.Note1_inc="";
					CurrentElementCopy.Note2_inc="[file]";
					CurrentElementCopy.Path_inc=fileInfo.path();
					CurrentElementCopy.ID_inc=fileInfo.path()+"/"+fileInfo.fileName();
					CurrentElementCopy.set_relpath(CurrentElementCopy.Path_inc);
					FileList.insert(FileList.size(), CurrentElementCopy);

				};

		};

	return "t_FileList::update_from_dir() executed.";
}

//============================================================
/*
 заполняет описания относительного пути
 от заданного каталога
 Пока работает только в отношении подкаталогов -
 т.к. еслди путь не начинается с заданной строки,
 то относительный каталог не заполняется.
 //TODO: сделать заполнение с переходом между каталогами и т.п. т.е. ".\..\..\dir"
         возможно, смотри для этого void QDir::setPath ( const QString & path )
*/
int t_FileList::fill_relative_paths(QString _DirectoryPath)
{
	QList<t_FileListElement>::iterator FLIterator;
	QString TmpRPath,CurPath,CurFileName;
	int Length;
	Length=_DirectoryPath.size();
	for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		CurPath=FLIterator->get_path();
		CurFileName=FLIterator->get_file_full_name();
		if (CurPath.startsWith(_DirectoryPath))
		  {
			TmpRPath=CurPath.mid(Length);
			if (!TmpRPath.startsWith("/")) TmpRPath.prepend("/");

			FLIterator->set_relpath("."+TmpRPath);
			if (TmpRPath.length()>1) //only '/' ?
				  FLIterator->set_id("."+TmpRPath+"/"+CurFileName+"");
			 else FLIterator->set_id("."+TmpRPath+""+CurFileName+"");
			//qDebug() << "t_FileList::fill_relative_paths::(0229) TmpRPath=" << TmpRPath <<" ID=" << FLIterator->ID_inc <<"";
			//qDebug() << "t_FileList::fill_relative_paths:: FLIterator->get_ID()=" << (*FLIterator).get_ID();
		  };
	  };
	/*/
	for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		qDebug() << "t_FileList::add_relative_paths:: FLIterator.get_ID() = " << (*FLIterator).ID_inc;
	  };
	/**/
	return 0;
}


//============================================================


 /**/
//сохранение/восстановление в/из файла
// xml?
QString t_FileList::save_to_file(QString _FileFullName)
{
	//TODO!обработка пробелов и других спец символов
	const QString Listel_xmltag="t_FileListElement";
	const QString List_xmltag="t_FileList";
	const QString ListelProp_xmltag="t_FileListElementProperties";

	QDomDocument XmlDDoc;
	QString *ErrorMsg;
	int *ErrorLine,*ErrorColomn;
	ErrorMsg=new QString;
	ErrorLine=new int;
	ErrorColomn=new int;
	bool rez1;
	QString RetValue;
	QDomElement XmlDDocRoot;

	XmlDDocRoot=XmlDDoc.createElement(List_xmltag);
	XmlDDoc.appendChild(XmlDDocRoot);

	QDomNode DomNode;
	QDomElement DomElement;
	QDomElement DomElementProp;
	QDomText DomText,DomText2;
	QDomAttr DomAttr;

	QList<t_FileListElement>::iterator FLIterator;
	QMap<QString,QString>::const_iterator i_prop;

	QString TmpRPath,CurPath,CurFileName;
	for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		DomElement=QDomElement();
		DomText=QDomText();
		//DomAttr=QDomAttr();

		//обработки данных "засовываемых" в XML не требуется, потому как
		// QtXML сам все сделает как при записи так и при чтении.


		DomText=XmlDDoc.createTextNode(FLIterator->ID_inc);
		DomElement=XmlDDoc.createElement(Listel_xmltag);

		XmlDDocRoot.appendChild(DomElement);
		DomElement.setAttribute(QString("FileFullName_inc"),(FLIterator->FileFullName_inc));
		DomElement.setAttribute(QString("Note1_inc"),(FLIterator->Note1_inc));
		DomElement.setAttribute(QString("Note2_inc"),(FLIterator->Note2_inc));
		DomElement.setAttribute(QString("Path_inc"),(FLIterator->Path_inc));
		DomElement.setAttribute(QString("RelativePath_inc"),(FLIterator->RelativePath_inc));
		DomElement.setAttribute(QString("ID_inc"),(FLIterator->ID_inc));

		//теперь переберем атрибуты элемента и занесем их дерево (2008.12.04)
			DomText2=QDomText();
			//DomAttr=QDomAttr();

			DomText2=XmlDDoc.createTextNode("properties");
			DomElementProp=XmlDDoc.createElement(ListelProp_xmltag);

			DomElement.appendChild(DomElementProp);//именно как подветвь текущего тега
			if ( FLIterator->Properties.begin() != FLIterator->Properties.end() )
				for (i_prop = FLIterator->Properties.begin(); i_prop != FLIterator->Properties.end(); ++i_prop)
				  {
					if (!i_prop.key().isEmpty())
						DomElementProp.setAttribute(i_prop.key(),i_prop.value());
					//qDebug() << "setAttribute("<<i_prop.key()<<","<<i_prop.value()<<")";
				  };
			//DomElementProp.appendChild(DomText2);
		DomElement.appendChild(DomText);
	  };


		if (_FileFullName.isEmpty())
			return "EROR: Empty File Name";

		QFile File(_FileFullName);
		if (!File.open(QFile::WriteOnly | QFile::Text))
		  {
	//      QMessageBox::warning(this, tr("SAX Bookmarks"),
	//                           tr("Cannot write file %1:\n%2.")
	//                           .arg(fileName)
	//                           .arg(file.errorString()));
			 return "Cannot write file.["+_FileFullName+"]";
		  };
		 QString XMLEncodingToUse="UTF-8";
	     QDomNode xmlNode = XmlDDoc.createProcessingInstruction("xml","version=\"1.0\" encoding=\""+XMLEncodingToUse+"\"");
	     XmlDDoc.insertBefore(xmlNode, XmlDDoc.firstChild());

		 QTextStream OutTStrem(&File);
		 XmlDDoc.save(OutTStrem, 5);

		return "File saved. ["+_FileFullName+"]";
}

//============================================================
/*

Схема документа списка файлов ver.2008.11.26
<t_FileList>
 <t_FileListElement filelistelement.name="name" >
 filelistelement.id
 </t_FileListElement>

</t_FileList>


*/
QString t_FileList::load_from_file(QString _FileFullName)
{
	const QString Listel_xmltag="t_FileListElement";
	const QString List_xmltag="t_FileList";
	const QString ListelProp_xmltag="t_FileListElementProperties";

	QDomDocument XmlDDoc;

	QString *ErrorMsg;
	int *ErrorLine,*ErrorColomn;
	ErrorMsg=new QString;
	ErrorLine=new int;
	ErrorColomn=new int;
	bool rez1;
	QString RetValue;//
	QByteArray line,XmlSrc;

				QFile file(_FileFullName);
				XmlSrc.clear();

				if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
					{
						return ("[ERROR] t_FileList::load_from_file()::[0349]: Error while loading file ["+_FileFullName+"]");
					};

				while (!file.atEnd())
					{ //тут надо отследить кодировки
						line = file.readLine();
						XmlSrc.append(QString().append(line));
					};

	rez1=XmlDDoc.setContent(XmlSrc, ErrorMsg, ErrorLine , ErrorColomn);

	/*/
	rez1=XmlDDoc.setContent(QString("\
			<t_FileList>\
				<t_FileListElement \
					FileFullName_inc=\"FileFullName_inc\"\
					Note1_inc=\"Note1_inc\"\
					Note2_inc=\"Note2_inc\"\
					Path_inc=\"Path_inc\"\
					RelativePath_inc=\"RelativePath_inc\"\
				  >ID_inc</t_FileListElement>\
				<t_FileListElement \
					FileFullName_inc=\"FileFullName_inc--2\"\
					Note1_inc=\"Note1_inc--2\"\
					Note2_inc=\"Note2_inc--2\"\
			      >To err is human</t_FileListElement>\
			</t_FileList>"), ErrorMsg, ErrorLine , ErrorColomn);//for testing
	/**/
	if (rez1==false)
	  {
	    qDebug() << "Error msg:: " << *ErrorMsg << " at line" << *ErrorLine <<" Colomn " << *ErrorColomn ;
	    RetValue= QString("Error msg:: %1 at Line %2 Colomn %3").arg(*ErrorMsg).arg(*ErrorLine).arg(*ErrorColomn);
	    return RetValue;
	  };

	QDomElement XmlDDocRoot = XmlDDoc.documentElement();


	if (XmlDDocRoot.tagName().trimmed().toLower()!=List_xmltag.trimmed().toLower())
		{
			qDebug() << "Error msg:: root xml tag is not <"+List_xmltag+">. Data can`t be loaded/";
			RetValue= "Error msg:: "+ *ErrorMsg + " at Line" + *ErrorLine + " Colomn " + *ErrorColomn;
			return RetValue;
		};


	t_FileListElement TmpElement;
	QDomElement DomElement,DomElementTMP;
	QDomNode DomNodeTMP;
	QDomNamedNodeMap AttrNameNode;

	QDomNode DomNode = XmlDDocRoot.firstChild();
	while(!DomNode.isNull())
	  {
		 DomElement = DomNode.toElement();
	     //Получили узел
	     if(!DomElement.isNull())
		   {
	    	 if (DomElement.tagName().trimmed().toLower()!=Listel_xmltag.trimmed().toLower())
	    		 continue; //незнакомые теги пропускаем.
	    	 TmpElement = t_FileListElement();//новый создадим
	    	 TmpElement.ID_inc=DomElement.text();
	    	 TmpElement.FileFullName_inc=DomElement.attribute("FileFullName_inc","");
			 TmpElement.Note1_inc		=DomElement.attribute("Note1_inc","");
			 TmpElement.Note2_inc		=DomElement.attribute("Note2_inc","");
			 TmpElement.Path_inc		=DomElement.attribute("Path_inc","");
			 TmpElement.RelativePath_inc=DomElement.attribute("RelativePath_inc","");

			 // у данного узла должен ыть 1 дочерний - ListelProp_xmltag
			 ;
			 for(DomNodeTMP = DomElement.firstChild(); !DomNodeTMP.isNull(); DomNodeTMP = DomNodeTMP.nextSibling())
			  {
				   DomElementTMP = DomNodeTMP.toElement();
				   if(!DomElementTMP.isNull())
					{
						 if (DomElementTMP.tagName().trimmed().toLower()==ListelProp_xmltag.trimmed().toLower())
						   {
						   }
						 else
						   {
							 //qDebug() <<"    tag \n"<<  DomElementTMP.tagName().trimmed().toLower() << " - vs - \n"<< ListelProp_xmltag.trimmed().toLower() ;
							 continue; //незнакомые теги пропускаем.
						   };
						 // текстовку у нутри тега не анализируем (пока?)

						 //переберем атрибуты
						 AttrNameNode=DomElementTMP.attributes();
						 for (int q=0;q<AttrNameNode.length();q++) //перебор атрибутов данного тега
						  {
							 TmpElement.set_property(AttrNameNode.item(q).toAttr().name(),AttrNameNode.item(q).toAttr().value());
							 //qDebug() <<"    attr: "<<  AttrNameNode.item(q).toAttr().name()<< "=" <<  AttrNameNode.item(q).toAttr().value();
						  };

					};
				   //DomNodeTMP = DomNodeTMP.nextSibling();
			  };//while(!DomNodeTMP.isNull())


			 FileList.append(TmpElement);

			 /* пример того как перебирать атрибуты - не удалять*/
			 /*/
				 qDebug() <<" TAG:"<< DomElement.tagName() << "\n Text:"<< DomElement.text ();
				 AttrNameNode=DomElement.attributes();
				 for (int q=0;q<AttrNameNode.length();q++) //перебор атрибутов данного тега
					 qDebug() <<"    attr: "<<  AttrNameNode.item(q).toAttr().name()<< "=" <<  AttrNameNode.item(q).toAttr().value();
	    	 /**/
		   };
	     DomNode = DomNode.nextSibling();
	  };

	 return "loaded ok";
}

//============================================================
/**/
//

// пересечь множество файлов
int t_FileList::intersect(t_FileList *OtherFileList)
{
	QSet<t_FileListElement> OtherFileSet = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	FileSet=QSet<t_FileListElement>::fromList(FileList);
	FileSet.intersect(OtherFileSet);
	FileList=QList<t_FileListElement>::fromSet(FileSet);
	FileSet.clear();
	return 0;
}

// объединить множества
int t_FileList::unite(t_FileList *OtherFileList)
{
	QSet<t_FileListElement> OtherFileSet = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	FileSet=QSet<t_FileListElement>::fromList(FileList);
	FileSet.unite(OtherFileSet);
	FileList=QList<t_FileListElement>::fromSet(FileSet);
	FileSet.clear();
	return 0;
}

// вычесть множества
int t_FileList::subtract(t_FileList *OtherFileList)
{
	QSet<t_FileListElement> OtherFileSet = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	FileSet=QSet<t_FileListElement>::fromList(FileList);
	FileSet.subtract(OtherFileSet);
	FileList=QList<t_FileListElement>::fromSet(FileSet);
	FileSet.clear();
	return 0;
}

// объединить без пересечения (XOR)
int t_FileList::exclusive_unite(t_FileList *OtherFileList)
{
	QSet<t_FileListElement> OtherFileSet1 = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	QSet<t_FileListElement> OtherFileSet2 = OtherFileSet1;
	FileSet=QSet<t_FileListElement>::fromList(FileList);
	OtherFileSet1.intersect(FileSet);
	FileSet.unite(OtherFileSet2);
	FileSet.subtract(OtherFileSet1);
	FileList=QList<t_FileListElement>::fromSet(FileSet);
	FileSet.clear();
	return 0;
}

//===========================================================================
t_FileList* t_FileList::copy()
{
	t_FileList *El;
	El=new t_FileList();
	*El=*this;
	return El;
}

//===========================================================================

//QTreeWidget*  t_FileList::create_tree_widget()
t_TreeWidget*  t_FileList::create_tree_widget(QString PropertyOrder)
{
// должен быть выполнен make_tree_struct()
//создаем виджет с отображением этого списка.
// сразу линкуем его с нашим объектом.. КАК?
//

	QStringList PropertyOrderList = QString(PropertyOrder).split(",");

	t_TreeWidget *QtsTreeWidget;
	QtsTreeWidget=new t_TreeWidget;

	 //RelativePath_inc - это и есть идентификатор для "родителя"
	 //создасть список QTreeWidgetItem
	 QMap<QString, QTreeWidgetItem*> TWIMap; //собрание ссылок на WidgetItem для организации в дерево

	 QTreeWidget *treeWidget;// = new QTreeWidget();
	 treeWidget=QtsTreeWidget->CoreQTreeWidget;
	 QTreeWidgetItem *treeWidgetItem;
	 // QTreeWidgetItem *treeWidgetItem_tmp;
	 QList<QTreeWidgetItem *> items; //список корневых элементов

	 PropertyOrderList.prepend("");
	 treeWidget->setColumnCount(PropertyOrderList.size());

	 //QString TmpRPath,CurPath,CurFileName;

	 int col=1;
	 //создадим виджеты для всех элементов списка
	 QList<t_FileListElement>::iterator FLIterator;
	 for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		if (!TWIMap.contains(FLIterator->ID_inc)) //вообще не должно быть такого но вдруг... что бы не плодить вхождения в карту...
		  {
			  treeWidgetItem= FLIterator->create_tree_widget_item(PropertyOrder)->CoreQTreeWidgetItem;
			  //treeWidgetItem->setBackground(col,QBrush(QColor (200, 201,203)));
			  //if (col<4) col++ ;
			  //	  else col=1;
			  TWIMap.insert(FLIterator->ID_inc, treeWidgetItem);
		  };
	  };

	 //пробежимся и организуем их в дерево
	 for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		//если он сам себе родитель - в корень его и не будем "думать".
		if (FLIterator->RelativePath_inc == FLIterator->ID_inc)
			{
			    items.append(TWIMap.value(FLIterator->ID_inc));
				continue;  //элементы у которых корень - пусто - пропускаем.
			};

		//qDebug()<<"Serching parent [" << FLIterator->RelativePath_inc <<"] for [" << FLIterator->ID_inc <<"]";
		if (!TWIMap.contains(FLIterator->RelativePath_inc))
		  { //если родительского элемента не найдено, то его надо в список корневых элементов...
			items.append(TWIMap.value(FLIterator->ID_inc));
			//qDebug()<<"     not found - it will bw a root element";
		  }
		else
	 	  { //Если родительский элемент найден...
			// ему надо подчинить себя...
			//qDebug()<<"   parent present.";
			TWIMap.value(FLIterator->RelativePath_inc)->addChild(TWIMap.value(FLIterator->ID_inc));
		  };
	  };
	 //корневые элементы - на виджет...остальные сами подтянутся с ними..
	 treeWidget->insertTopLevelItems(0, items);

 	 treeWidget->setHeaderLabels(PropertyOrderList);

//	 treeWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
	 return QtsTreeWidget;
}

//===========================================================================
// выделить структуру дерева, родителей и т.п. по полю RelativePath_inc
// добавит в список элементы для групп и каталогов
int t_FileList::make_tree_struct()
{

	 FileSet=QSet<t_FileListElement>::fromList(FileList);//множество объектов идентифициремых по ID
	 t_FileListElement TmpFileListEl;

	 QList<t_FileListElement>::iterator FLIterator;

	 //суть цикла - найти недостающие элементы-группы, для них - их группы
	 // и так далее до корня...
	 for (FLIterator = FileList.begin(); FLIterator != FileList.end(); ++FLIterator)
	  {
		 //RelativePath_inc - это и есть идентификатор для "родителя"
		 TmpFileListEl.ID_inc=FLIterator->RelativePath_inc;
		 //идентификация элементов в множестве для t_FileListElement
		 // производится по полю ID_inc
		 // следовательно, можно не заполнять остальные элементы
		 if (TmpFileListEl.ID_inc.trimmed().isEmpty() | TmpFileListEl.ID_inc.trimmed()=="." | TmpFileListEl.ID_inc.trimmed()=="./")
				  continue;  //элементы у которых корень - пусто - пропускаем
							 // потому что это они собственно корневые верхнего уровня и есть.
							 // и добавлять дляних пустой корень не стоит. более того - если пустой корень добавить
							 // то его надо будет отлавливать и не позволять подчинить его самому себе позже при построени дерева
		 if (!FileSet.contains(TmpFileListEl))
		  {//нет такого элемента
			 // в относительный путь надо засунуть путь без последнего элемента.
			  // т.к. в QT классах пути всегда с "/" - нам проще )
			 TmpFileListEl.RelativePath_inc=TmpFileListEl.ID_inc.left(TmpFileListEl.ID_inc.lastIndexOf("/"));
			  // а в имя - тот самый последний элемент.
			 TmpFileListEl.FileFullName_inc=TmpFileListEl.ID_inc.mid(TmpFileListEl.ID_inc.lastIndexOf("/")+1);

			TmpFileListEl.Note1_inc="[--dir-element--]";
			FileSet.insert(TmpFileListEl);
			// далее - добавляем новый элемент в конец списка что бы потом и для него создать его родителя.
			FileList.append(TmpFileListEl);//будем надеяться выборка итератора при этом не сбросится...
		  };
	  };
	 FileList=QList<t_FileListElement>::fromSet(FileSet);

	 return 0;
};


//===========================================================================
int t_FileList::unite_w_properties(t_FileList *OtherFileList, bool ReplacePropertyValues, bool UnitePropertySets)
{
//TODO: СДЕЛАТЬ ТЕСТИРОВАНИЕ МЕТОДА!!!!
	//при объединении с учетом атриутов - нас интересуют в первую очередь пересекающиеся элементы
	// потому с них и начнем.
	QList<t_FileListElement> FileList_L;
	FileList_L = get_intersection_w_properties(OtherFileList, ReplacePropertyValues, UnitePropertySets);
	QSet<t_FileListElement> UnitedPropSet = QSet<t_FileListElement>::fromList(FileList_L);

	//далее - надо получить объединение,
	// вычесть их него пересечение и ещё раз добавить туда переечение, но уже с нужными нам атрибутами
	QSet<t_FileListElement> OtherFileSet2 = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	FileSet=QSet<t_FileListElement>::fromList(FileList);

	FileSet.unite(OtherFileSet2);
	FileSet.subtract(UnitedPropSet);// удалим что бы точно знать что при объединении
	FileSet.unite(UnitedPropSet);   //  в конечное множество будет перенесены нужные нам копии
	this->FileList=QList<t_FileListElement>::fromSet(FileSet);
	FileSet.clear();
}

//======================================================================
//объединим множества с учетом объединения/замещения атрибутов элементов
int t_FileList::intersect_w_properties(t_FileList *OtherFileList, bool ReplacePropertyValues, bool UnitePropertySets)
{
	this->FileList = get_intersection_w_properties(OtherFileList, ReplacePropertyValues, UnitePropertySets);
	return 0;
};

//======================================================================
QList<t_FileListElement> t_FileList::get_intersection_w_properties(t_FileList *OtherFileList, bool ReplacePropertyValues, bool UnitePropertySets)
{
	QSet<t_FileListElement> OtherFileSet = QSet<t_FileListElement>::fromList(OtherFileList->FileList);
	QSet<t_FileListElement> CurrentFileSet=QSet<t_FileListElement>::fromList(FileList);
	QSet<t_FileListElement>::const_iterator Other_SetEl;
	QSet<t_FileListElement>::const_iterator Current_SetEl;

	QSet<t_FileListElement> FileSet_L;
	QList<t_FileListElement> FileList_L;



	FileSet_L=CurrentFileSet;
	FileSet_L.intersect(OtherFileSet);
	FileList_L=QList<t_FileListElement>::fromSet(FileSet_L);
			//вынуждены использовать QList потому что надо менять элемент в течении перебора
			//т.к. изменять элемент внутри QSet нельзя
	FileSet_L.clear();
	QMap<QString,QString> TmpPropertySet;

	t_FileListElement TmpFileListEl;

	QList<t_FileListElement>::iterator i;

	//i = FileSet_L.begin();
	//while (i != FileSet_L.end())
	for (i = FileList_L.begin(); i != FileList_L.end(); ++i)
	  {
		 //TmpFileListEl.ID_inc=i->ID_inc;//идентификация элементов - по ID_inc потому можно остальное не заполнять.
		 TmpFileListEl.ID_inc=i->get_id();//идентификация элементов - по ID_inc потому можно остальное не заполнять.
		 // найдем оригиналы в исходных множествах
		 Current_SetEl=CurrentFileSet.find(TmpFileListEl);
		 if (Current_SetEl==CurrentFileSet.constEnd()) //не нашли элементы
		   {
			 qDebug() << "t_FileList::get_intersection_w_properties():0683::ERROR! CurrentFileSet.find(TmpFileListEl) - NOT FOUND! PANIC!";
			 //ЧТО-ТО Страшное случилось... не должны сюда попасть
			 // т.к. исходное перебираемое множество - это перечечение первого и второго.
			 // Изменился механизм идентификации t_FileListElement ?!
		   };
		 Other_SetEl=OtherFileSet.find(TmpFileListEl);//ТУТ ОТДАЕТСЯ CONST_ITERATOR! потому что QSET!
		 if (Other_SetEl==OtherFileSet.constEnd()) //не нашли элементы
		   {
			 qDebug() << "t_FileList::get_intersection_w_properties():0691::ERROR! OtherFileSet.find(TmpFileListEl) - NOT FOUND! PANIC!";
			 //ЧТО-ТО Страшное случилось... не должны сюда попасть
			 // т.к. исходное перебираемое множество - это перечечение первого и второго.
			 // Изменился механизм идентификации t_FileListElement ?!
		   };

		 //теперь надо перенести свойства из этих элементов в i;
		 /*
		 4 варианта
			 ReplacePropertyValues=true, Замещать с объединением
			 UnitePropertySets=true

			 ReplacePropertyValues=false, НеЗамещать с объединением
			 UnitePropertySets=true

			 ReplacePropertyValues=true, Замещать без объединения (взять все у нового множества)
			 UnitePropertySets=false

			 ReplacePropertyValues=false, НЕ Замещать без объединения (отсавить все как у старого множества)
			 UnitePropertySets=false
		 */

		  TmpPropertySet.clear();
		  if (UnitePropertySets)
			{//объединять элементы
			  if (ReplacePropertyValues)
				  { //с приоритетом новых
					  TmpPropertySet=Current_SetEl->Properties;
					  //foreach (QString value, QString key, Other_SetEl->Properties)
					  //TmpPropertySet[key]=value;

					  QMap<QString, QString>::const_iterator Other_SetEl_i;
					  //qDebug() << "(Other_SetEl->Properties).size()=" <<(Other_SetEl->Properties).size();
					  if ((Other_SetEl->Properties).size() != 0 )
						  for (Other_SetEl_i = (Other_SetEl->Properties).constBegin(); Other_SetEl_i != (Other_SetEl->Properties).constEnd(); ++Other_SetEl_i)
							{
							  //qDebug() << Other_SetEl_i.value() << endl;
							  //qDebug() <<"Other_SetEl_i.key()=" <<  Other_SetEl_i.key();
							  //qDebug() <<"Other_SetEl_i.value()=" << Other_SetEl_i.value();
							  TmpPropertySet[Other_SetEl_i.key()]=Other_SetEl_i.value();
							};
				  }
			  else //if (ReplacePropertyValues)
				  { //с приоритетом старых
					  TmpPropertySet=Other_SetEl->Properties;
					  //foreach (QString value,QString key, Current_Set->Properties)
					  //	  TmpPropertySet[key]=value;

					  QMap<QString, QString>::const_iterator Current_SetEl_i = Current_SetEl->Properties.constBegin();
					  while (Current_SetEl_i != Current_SetEl->Properties.constEnd())
					    {
						  TmpPropertySet[Current_SetEl_i.key()]=Current_SetEl_i.value();
					      ++Current_SetEl_i;
					    };

				  };//if (ReplacePropertyValues)

			  }//if (UnitePropertySets)
		  else //Замещать
			  if (ReplacePropertyValues)
				  {
				    TmpPropertySet=Other_SetEl->Properties;
				  }
			  else
				  {
				    TmpPropertySet=Current_SetEl->Properties;
				  };

		  //надо удалить и вставить...
		  i->Properties=TmpPropertySet;

	    // ++i;//becouse FOR
	  };//while (i != FileSet_L.constEnd())
	//FileList_L=QList<t_FileListElement>::fromSet(FileSet_L);
	return FileList_L;

}

//======================================================================
//=/* групповые операции над атрибутами множествами */==================
//установить у элементов свойства
// 2008.12.02
int t_FileList::set_property(QString _ValueName,QString _ValueVar)
{
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		i->set_property(_ValueName,_ValueVar);
	  };
	return 0;
}

//=/* групповые операции над атрибутами множествами */==================
//вернуть количество элементов в которых определено свойство
// 2008.12.02
int t_FileList::count_item_property_enteries(QString _ValueName)
{
	int counter;
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		if (i->is_property_contains(_ValueName)) counter++;
	  };
	return counter;
}

//=/* групповые операции над атрибутами множествами */==================================================================
//удалить заданное свойство элементов
// 2008.12.02
int t_FileList::remove_item_property(QString _ValueName)
{
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		i->remove_property(_ValueName);
	  };
	return 0;
}

//=/* групповые операции над атрибутами множествами */==================================================================
//удалить все свойства элементов
// 2008.12.02
int t_FileList::remove_all_item_properties()
{
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		i->remove_all_properties();
	  };
	return 0;
}

//=/* групповые операции над атрибутами множествами */==================================================================
//переименовать свойство.
// 2008.12.02
int t_FileList::rename_item_property(QString _ValueNameOld, QString _ValueNameNew, bool Replace)
{
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		i->rename_property(_ValueNameOld, _ValueNameNew, Replace);
	  };
	return 0;
}

//===============================================================
// сгенерировать список элементов из текущего
// по признаку
t_FileList* t_FileList::sort_out_by_property(QString _ValueName,QString _ValueVar)
{
	int counter;
	QString VarVal2;
	VarVal2=_ValueVar.trimmed().toLower();//нужна регистронезависимость.

	t_FileList* NewFileList;
	NewFileList = new t_FileList();
	QList<t_FileListElement>::iterator i;
	for (i = FileList.begin(); i != FileList.end(); ++i)
	  {
		if (i->get_property(_ValueName).trimmed().toLower()== VarVal2)
		  {
			NewFileList->FileList.append(*i);
		  };//if (i->get_property(_ValueName).trimmed().toLower()== VarVal2)
	  };//for (i = FileList.begin(); i != FileList.end(); ++i)

	return NewFileList;
}
